import os								# 系统模块
import re                               # 正则表达式
import csv								# csv表格
import json								# json数据解析
import jieba                            # 分词
import urllib3							# 爬虫模块
import requests							# 爬虫模块
import numpy as np                      # 矩阵运算
from tkinter import *					# 窗口
from urllib import request				# json数据解析
from time import perf_counter			# 计时模块
from PIL import Image, ImageTk			# 图片处理
from tkinter import messagebox
from wordcloud import WordCloud         # 词云
from matplotlib import pyplot as plt    # 绘图，数据可视化

'''
数据抓取模块
'''

def info():
    start = perf_counter()
    a = inp1.get()  # 获取文本框输入内容
    if a == '':
        messagebox.showinfo('提示', '请输入要视频的BVID')
    else:
        url = 'https://api.bilibili.com/x/web-interface/view?bvid=' + a
        # https://www.bilibili.com/video/BV17V411x7qX?spm_id_from=333.851.b_7265636f6d6d656e64.2
        # 利用API获取视频信息
        url1 = 'https://www.bilibili.com/video/'+a
        headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
        }
        # 请求头，模拟浏览器的运行

        urllib3.disable_warnings()                      # 从urllib3中消除警告

        response = requests.get(url, headers=headers)   # 请求网页响应

        content = json.loads(response.text)             # 将网页解析为字符串
        # 获取到的是json字符串 需要解析成str数据
        # print(response.content.decode('utf-8'))

        statue_code = content.get('code')               # 请求网页状态码
        # print(statue_code)

        if statue_code == 0:
            title = content['data']['title']
            cid = content['data']['cid']                     # UP主的CID
            duration = content['data']['duration']           # 视频时长
            view = content['data']['stat']['view']           # 观看次数
            danmaku = content['data']['stat']['danmaku']     # 弹幕条数
            reply = content['data']['stat']['reply']         # 评论条数
            favorite = content['data']['stat']['favorite']   # 收藏人数
            coin = content['data']['stat']['coin']           # 投币数
            share = content['data']['stat']['share']         # 分享次数
            like = content['data']['stat']['like']           # 喜欢次数
            data = content['data']['pic']                    # 封面信息
            head = content['data']['owner']['face']         # 头像信息

        # print(data)
        # print(head)

        name = 'output\封面.jpg'
        request.urlretrieve(data, filename=name)
        # 将头像图片下载到本地

        face = 'output\头像.jpg'
        request.urlretrieve(head, filename=face)
        # 将头像图片下载到本地

        print('视频名字:', title)
        print('UP主的CID:', cid)
        print('视频时长:', duration, '秒')
        print('观看次数:', view, '次')
        print('弹幕条数:', danmaku, '个')
        print('评论条数:', reply, '条')
        print('收藏人数:', favorite, '人')
        print('投币数:', coin, '枚')
        print('分享次数:', share, '次')
        print('点赞人数:', like, '人')

        txt.insert(END, ('视频名字:' + str(title) + '\n'))
        txt.insert(END, '\n')
        txt.insert(END, ('完整链接:' + str(url1) + '\n'))
        txt.insert(END, '\n')
        txt.insert(END, ('UP主的CID:' + str(cid) + ' '))
        txt.insert(END, ('视频时长:' + str(duration) + '秒' + ' '))
        txt.insert(END, ('观看次数:' + str(view) + '次' + '\n'))
        txt.insert(END, '\n')
        txt.insert(END, ('弹幕条数:' + str(danmaku) + '个' + ' '))
        txt.insert(END, ('评论条数:' + str(reply)+'条' + ' '))
        txt.insert(END, ('分享次数:' + str(share) + '次' + '\n'))
        txt.insert(END, '\n')
        txt.insert(END, ('点赞人数:' + str(like) + '人' + ' '))
        txt.insert(END, ('收藏人数:' + str(favorite) + '人' + ' '))
        txt.insert(END, ('投币数:' + str(coin) + '枚' + '\n'))
        txt.insert(END, '\n')

        end = perf_counter()

        print("运行时间是:{:.5f}s".format(end - start))
        txt.insert(END, ("头像和封面已经保存到output目录了 我只用了{:.2f}秒就找到咯~".format(end - start)))
        # inp1.delete(0, END)  # 清空输入

def danmu():
    a = inp1.get()  # 获取文本框输入内容
    if a == '':
        messagebox.showinfo('提示', '请输入要视频的BVID')
    else:
        # txt.delete(0, END)  # 清空文本框内容
        start = perf_counter()
        url = 'https://www.bilibili.com/video/'+a
        res = requests.get(url)
        cid = re.findall(r'"cid":(.*?),', res.text)[-1]
        url = f'https://comment.bilibili.com/{cid}.xml'
        res = requests.get(url)
        with open(f'output\{cid}.xml', 'wb') as f:
            f.write(res.content)
        # print(cid)

        with open(f'output\{cid}.xml', encoding='utf-8') as f:
            data = f.read()

        comments = re.findall('<d p="(.*?)">(.*?)</d>', data)
        # print(len(comments))  # 3000
        danmus = [','.join(item) for item in comments]
        headers = ['出现时间', '模式', '大小', '颜色', '日期', 'pool', '作者', '作者bid', '弹幕内容']
        headers = ','.join(headers)
        danmus.insert(0, headers)
        path = "output\danmus.csv"
        if (os.path.exists(path)):  # 判断文件是否存在
            os.remove(path)         # 删除文件
        with open('output\danmus.csv', 'w', encoding='utf_8_sig') as f:
            f.writelines([line + '\n' for line in danmus])
        end = perf_counter()
        time = end - start
        txt.insert(END, ('弹幕文件已经保存到程序output目录咯'))
        txt.insert(END, '\n')
        txt.insert(END, ("我只用了{:.2f}秒就爬取成功咯~".format(end - start)))

def wordcloud():
    start = perf_counter()
    with open('output\danmus.csv', 'rt', encoding='utf-8') as csvfile:
        reader = csv.reader(csvfile)
        word = [row[8] for row in reader]
        csvfile.close()
    # print(word)
    word1 = str(word)
    # print((word))
    # 只保留中文、大小写字母和阿拉伯数字
    pattern = "[^0-9A-Za-z\u4e00-\u9fa5]"
    word2 = re.sub(pattern, '', word1)
    # print(word2)
    # print(re.sub(pattern, '', word1))

    # 分词
    cut = jieba.cut(word2)  # 使用jieba分词
    string = ' '.join(cut)  # 将空格插入每两个词语之间
    # print(string)

    img = Image.open(r'media\tree.jpg')  # 打开遮罩图片
    img_array = np.array(img)  # 将图片转换成数组
    wc = WordCloud(
        background_color='white',  # 设置背景
        mask=img_array,  # 设置遮罩，也就是树的形状
        font_path="msyh.ttc",  # 设置字体
    )
    wc.generate_from_text(string)  # 切词

    # 绘制图片
    fig = plt.figure(1)
    plt.imshow(wc)  # 将词云显示出来，也就是词语
    plt.axis('off')  # off为不显示坐标轴

    # plt.show()  #显示生成的词云图片
    # if os.path.exists(word.jpg):
    #     os.remove(word.jpg)
    # 输出词云图片到文件
    plt.savefig(r'word.jpg')
    end = perf_counter()
    txt.insert(END, ('词云已经保存到程序所在目录咯'))
    txt.insert(END, '\n')
    txt.insert(END, ("我只用了{:.2f}秒就画完成功咯~".format(end - start)))


'''
窗口模块
'''

root = Tk()
# 创建新的窗口

sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
# 得到屏幕宽度和高度

ww = 500
wh = 300
# 窗口宽高为500*300

x = (sw-ww) / 2
y = (sh-wh) / 2
root.geometry("%dx%d+%d+%d" % (ww, wh, x, y))

root.title('Bilibili视频信息获取程序')

canvas = Canvas(root,
                    width=500,  # 指定Canvas组件的宽度
                    height=300,  # 指定Canvas组件的高度
                    bg='white')  # 指定Canvas组件的背景色
# im = Tkinter.PhotoImage(file='img.gif')     # 使用PhotoImage打开图片
image = Image.open("media/1.png")
im = ImageTk.PhotoImage(image)

canvas.create_image(250, 150, image=im)  # 使用create_image将图片添加到Canvas组件中

canvas.pack()  # 将Canvas添加到主窗口

lb1 = Label(canvas, text='请输入视频的BID(www.bilibili.com/video/后不包括问号的字符串):')
lb1.pack()
# lb2 = Label(root, text='如https://www.bilibili.com/video/BV1FU4y1j7Me取BV1FU4y1j7Me')
# lb2.pack()
inp1 = Entry(canvas, justify='center')
inp1.pack(pady=20)
# 调整三个框框的位置
frame = Frame(canvas)
frame.pack()

btn1 = Button(frame, text='获取视频信息', command=info).grid(column=0, row=0)

btn2 = Button(frame, text='保存弹幕文件', command=danmu).grid(column=1, row=0)

btn3 = Button(frame, text='绘制词云', command=wordcloud).grid(column=2, row=0)

# 直接使用command调用函数

txt = Text(canvas, width=80)
txt.pack(pady=10)

root.mainloop()
